package br.unifor.mia.sd.proxy;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

public class IncomingRequestHandler implements Runnable {

	/** Outcoming socket */
	Socket clientSocket = null;

	Logger log = Logger.getLogger("br.unifor.mia.sd.proxy");

	public IncomingRequestHandler(Socket socket) {
		clientSocket = socket;
	}

	@Override
	public void run() {

		if (log.isLoggable(Level.FINEST)) {

			log.log(Level.FINEST, "Connection Accepted. "
					+ clientSocket.getInetAddress() + ":"
					+ clientSocket.getPort() + ".");
		}

		try {
			/*
			 * Initialing input and output stream. So, the class can read and
			 * write from / into the socket
			 */

			byte[] msgBytes = readBytesFromClient();
			HttpMessage message = new HttpMessage(msgBytes);

			if (log.isLoggable(Level.FINEST)) {
				log.log(Level.FINEST, "Pacote Http Recebido:\n"
						+ new String(message.getMessage()));
			}

			DispatcherFactory factory = new DefaultDispatcherFactory();
			Dispatcher dispatcher = factory.createDispatcher(message);
			HttpMessage response = dispatcher.dispatch(message);

			// Sending the response to the client
			sendBytesToClient(response.getMessage());
			
			// Closing Connections
			clientSocket.close();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidCreationException ice) {
			// TODO Auto-generated catch block
			ice.printStackTrace();
		}
	}

	private byte[] readBytesFromClient() throws IOException {
		InputStream in = clientSocket.getInputStream();
		ByteArrayOutputStream out = new ByteArrayOutputStream();

		while (in.available() > 0) {
			out.write(in.read());
		}
		return out.toByteArray();
	}

	private void sendBytesToClient(byte[] message) throws IOException {
		OutputStream out = clientSocket.getOutputStream();
		out.write(message);
	}
}
